package container

import (
	"gitee.com/huanminabc/go-utils/code_analysis"
	"gitee.com/huanminabc/go-utils/common"
	"gitee.com/huanminabc/go-utils/encrypt"
	"go-LineScriptCommand/global"
	"reflect"
	"runtime"
	"strings"
)

// Fun 函数
type Fun func(args ...string) string

// 冲突函数名称映射表
var conflictFun = map[string]string{
	"_if_":     "if",
	"_for_":    "for",
	"_len_":    "len",
	"_max_":    "max",
	"_min_":    "min",
	"_pi_":     "PI",
	"_system_": "system",
	"_file_":   "file",
}

// 提取函数名
func GetFunctionName(func1 Fun) string {
	//获取函数名
	funcName := runtime.FuncForPC(reflect.ValueOf(func1).Pointer()).Name()
	//截取函数名
	funcName = funcName[strings.LastIndex(funcName, ".")+1:]
	//如果是冲突函数名称,则替换
	if v, ok := conflictFun[funcName]; ok {
		return v
	}
	return funcName
}

// 类型分组
var mapType = make(map[string][]Fun)

// RegisterType 注册类型
func RegisterType(name string, f []Fun) {
	//判断是否是映射表中的函数
	if v, ok := conflictFun[name]; ok {
		name = v
	}
	if _, ok := mapType[name]; ok {
		panic("类型已经注册过了")
	}
	mapType[name] = f
}

// 获取mapType
func GetMapType() map[string][]Fun {
	return mapType
}

// 注册函数容器
var funList = make(map[string]Fun)

// RegisterFun 注册函数
func RegisterFun(name string, f Fun) {
	//判断是否是映射表中的函数
	if v, ok := conflictFun[name]; ok {
		name = v
	}
	if _, ok := funList[name]; ok {
		panic(name + "函数已经注册过了")
	}
	funList[name] = f
}

// 批量注册函数,自动提取函数名
func RegisterFunList(funs []Fun) {
	for _, v := range funs {
		RegisterFun(GetFunctionName(v), v)
	}
}

// 获取是否存在
func IsExistFun(name string) bool {
	//判断是否是映射表中的函数
	if v, ok := conflictFun[name]; ok {
		name = v
	}
	if _, ok := funList[name]; ok {
		return true
	}
	return false

}

// 获取全部的函数名称
func GetAllFunName() []string {
	var names []string
	for name := range funList {
		//判断是否是映射表中的函数
		if v, ok := conflictFun[name]; ok {
			name = v
		}
		names = append(names, name)
	}
	return names
}

// ExecuteFun 执行函数   show  [1,2,3]
func ExecuteFun(name string, args ...string) string {
	//判断是否是映射表中的函数
	if v, ok := conflictFun[name]; ok {
		name = v
	}
	if f, ok := funList[name]; ok {
		return f(args...)
	}
	panic("函数未注册")
}
func ExecuteRealFun(fun Fun, args ...string) string {
	name := GetFunctionName(fun)
	return ExecuteFun(name, args...)
}

// 跳过的函数
var skipFun = []string{"scan", "system"}

// show(1,2,3)
func ExecuteFunCut(fun string) string {
	//提取字符串, 因为下面有函数,防止影响到函数
	_both_, _strOld_ := code_analysis.PickBoth(fun, global.StrSplitSymbol)
	//加工net函数
	_strOld_ = netFunCut(_strOld_)

	funName, funParam := code_analysis.GetFunNameAnrParam(_strOld_)
	if funName != "" && IsExistFun(funName) {
		//执行函数
		//将funParam转换为 []interface{}
		var funParamInterface []string
		for _, vp := range funParam {
			//去空
			vp = strings.TrimSpace(vp)
			//跳过scan函数解析函数, 因为内部会自习解析
			if common.SliceContains(&skipFun, funName) {
				//还原字符串
				vp = code_analysis.RestorePickBoth(vp, _both_)
				//取消引号
				vp = strings.ReplaceAll(vp, global.GetStrSplitSymbol(), "")
				funParamInterface = append(funParamInterface, vp)
				continue
			}

			_funp_ := IsExistFun(vp) //如果这个返回true,那么就是函数
			if _funp_ {
				vp = ExecuteFun(vp, []string{}...)
				funParamInterface = append(funParamInterface, vp)
				continue
			}
			//判断是否是函数
			fun_ := code_analysis.IsFunCall(vp) //如果这个返回true,那么就是函数,就需要执行函数把结果拿到
			if fun_ != "" {
				vp = code_analysis.RestorePickBoth(vp, _both_) //执行之前先把字符串还原不然就带入了
				//执行函数
				vp = ExecuteFunCut(vp)
				funParamInterface = append(funParamInterface, vp)
				continue
			}

			//还原字符串
			vp = code_analysis.RestorePickBoth(vp, _both_)
			//取消引号
			vp = strings.ReplaceAll(vp, global.GetStrSplitSymbol(), "")
			funParamInterface = append(funParamInterface, vp)
		}
		if funParamInterface == nil {
			funParamInterface = []string{}
		}

		return ExecuteFun(funName, funParamInterface...)
	}
	//如果funName不是空,但是不存在,那么就报错函数不存在
	if funName != "" {
		//判断是否是映射表中的函数
		if v, ok := conflictFun[funName]; ok {
			funName = v
		}
		panic("函数" + funName + "不存在")
	}
	return "%^%^%^%" //表示不是函数
}

// net函数加工
func netFunCut(_strOld_ string) string {
	//判断是net()函数,那么就需要将内容转换base64
	if strings.HasPrefix(_strOld_, "net(") {
		//先将换行符替换掉
		_strOld_ = strings.ReplaceAll(_strOld_, global.LineBreak, "")
		//是否存在,[
		if strings.Contains(_strOld_, ",[") {

		} else if strings.Contains(_strOld_, ",{") {
			//分割,{
			handleStrOld_ := strings.Split(_strOld_, ",{")
			//判断长度,如果是2,那么就是两个参数,第二个参数是body, 如果是3,那么就是三个参数,第三个参数是header
			if len(handleStrOld_) == 2 {
				//取出第二个参数
				handleStrOld_1 := "{" + handleStrOld_[1]
				//找到最后一个}然后截取
				handleStrOld_1 = handleStrOld_1[:strings.LastIndex(handleStrOld_1, "}")+1]

				//判断是否是json格式
				if common.IsValidJSONObject(handleStrOld_1) {
					//转换base64
					encode := encrypt.Base64StrEncode(handleStrOld_1)
					//替换
					handleStrOld_[1] = encode
					//还原
					_strOld_ = strings.Join(handleStrOld_, ",") + ")"
				}

			} else if len(handleStrOld_) == 3 {
				//取出第二个参数
				handleStrOld_1 := "{" + handleStrOld_[1]
				//找到最后一个}然后截取
				handleStrOld_1 = handleStrOld_1[:strings.LastIndex(handleStrOld_1, "}")+1]

				//判断是否是json格式
				if common.IsValidJSONObject(handleStrOld_1) {
					//转换base64
					encode := encrypt.Base64StrEncode(handleStrOld_1)
					//替换
					handleStrOld_[1] = encode
				}
				//取出第三个参数
				handleStrOld_2 := "{" + handleStrOld_[2]
				//找到最后一个}然后截取
				handleStrOld_2 = handleStrOld_2[:strings.LastIndex(handleStrOld_2, "}")+1]
				//判断是否是json格式
				if common.IsValidJSONObject(handleStrOld_2) {
					//转换base64
					encode := encrypt.Base64StrEncode(handleStrOld_2)
					//替换
					handleStrOld_[2] = encode
					//还原
					_strOld_ = strings.Join(handleStrOld_, ",") + ")"
				}

			} else {
				panic("net函数参数个数不正确")
			}

		}

	}
	return _strOld_
}
